/**
  ETFDAQ Project
  \class TAv830
  \brief 32 ch ECL input scaler VME module from CAEN Corp. of Italy
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2024-09-02
  \date 2024-09-02 last modified

  \copyright Copyright (c) 2024 IMP-CAS with LGPLv3 LICENSE
*/

#ifndef TAv830_h
#define TAv830_h

#include "TACAENCard.h"

class TAv830 : public TACAENCard{
public:
  TAv830(TAController *ctrl, const TAYaml &c);
  virtual ~TAv830();

  ///--- initialization ---///
  virtual void Initialize() override;
  virtual void Identify() override; ///< read card info (e.g. serialNo.)
  virtual void SlotInit() override; ///< write slot id and crate id
  /// \param level 1~7, 0 will disable the IRQ generation
  /// \param vector 0x00~0xFF, requested by vme ctrler to identify the interrupter
  /// \param nEv: trigger will be generated after nof buffered WORDS reaches len
  virtual void ConfigIRQ(int level, int vector, int nEv) const override;

  ///--- configuration ---///
  /// 32 bits corresponds to ch 0-31 respectively. 1: enable; 0:disable
  void SetChOnPattern(uint32_t pattern) const;
  /// reset counter regs, the MEB, the trig counter, and the MEB ev counter
  virtual void SoftwareReset() override;
  virtual void EnableEmpty() const override;

  ///--- the DAQ loop ---///
  virtual bool DataReady() const override; ///< true if buffered events are enough
  /// \retval nof words read
  /// NOTE that although implemeneted for 32 ch card via A32BLT32Read in TACard,
  /// this method is supposed to be speicifically implemented in sub-classes
  virtual int ReadEvent(uint32_t *buf) override;
  /// clear the module's multi-event buffers, the R/W pointers, and the event counters
  virtual void ClearData() override; // data reset (DR)
  virtual void ClearEventCounter() override; ///< clears the event counter
  virtual void ResetForNewRun() override;

  /// ---- print functions ---///
  /// \return the event counter register
  virtual void ReadEventCounter() override;
  virtual void PrintEvent(const uint32_t *ev)  override; ///< print one event
  virtual void Print() const override;
};


// control and data registers specifically for v830 //
struct v830reg{
  static constexpr uint16_t Buffer =             0x0000; // ~0x0FFF, 4096B
  static constexpr uint16_t Counter =            0x1000; // +ch*4, 0-31
  static constexpr uint16_t Testreg =            0x1080;
  static constexpr uint16_t Testlcntl =          0x1090; // for factory use only
  static constexpr uint16_t Testlcnth =          0x1094; // for factory use only
  static constexpr uint16_t Testhcntl =          0x10a0; // for factory use only
  static constexpr uint16_t Testhcnth =          0x10a4; // for factory use only
  static constexpr uint16_t ChannelEnable =      0x1100;
  static constexpr uint16_t DwellTime =          0x1104; // periodic trig dt
  static constexpr uint16_t Control =            0x1108;
  static constexpr uint16_t ControlBitSet =      0x110a;
  static constexpr uint16_t ControlBitClear =    0x110c;
  static constexpr uint16_t Status =             0x110e;
  static constexpr uint16_t GeoAddress =         0x1110;
  static constexpr uint16_t InterruptLevel =     0x1112;
  static constexpr uint16_t InterruptVector =    0x1114;
  static constexpr uint16_t ADER32 =             0x1116;
  static constexpr uint16_t ADER24 =             0x1118;
  static constexpr uint16_t EnableADER =         0x111a;
  static constexpr uint16_t MSCTAddress =        0x111c;
  static constexpr uint16_t MSCTControl =        0x111e;
  static constexpr uint16_t ModuleReset =        0x1120;
  static constexpr uint16_t SoftwareClear =      0x1122;
  static constexpr uint16_t SoftwareTrigger =    0x1124;
  static constexpr uint16_t TriggerCounter =     0x1128;
  static constexpr uint16_t AlmostFullLevel =    0x112c; // evTrig but in words
  static constexpr uint16_t BLTEventNumber =     0x1130; // evTrig via BLT
  static constexpr uint16_t FirmwareRev =        0x1132; // 0xf0.0xf
  static constexpr uint16_t MEBEventNumber =     0x1134; // nof buffered events
  static constexpr uint16_t Dummy32 =            0x1200;
  static constexpr uint16_t Dummy16 =            0x1204;
};

/////////// following are the masks of some registers /////////////////
struct v830mask{
  ///--- Status register ---///
  static constexpr uint16_t DRDY = 0x1; // data ready bit
  ///--- BitSet1 register ---///
  static constexpr uint16_t SOFTRESET = 0x80; // soft ware reset bit
  ///--- BitSet2 register ---///
  static constexpr uint16_t STEPTH = 0x100; // 1: large thre steps
  static constexpr uint16_t CLRDATA = 0x4; // clear data bit
  ///--- Control register ---///
  static constexpr uint16_t ACQMODELOW = 0x1; // ..ext. or via VME; 10: periodic trig
  static constexpr uint16_t ACQMODEHIGH = 0x2; // 00: trig disabled; 01: trig random..
  static constexpr uint16_t DATA_FORMAT = 0x4; // 0: 32bit(default), 1: 26bit
  static constexpr uint16_t BERR_ENABLE = 0x10; // give a berr upon a blk transfer
  static constexpr uint16_t HEADER_ENABLE = 0x20; // save header in an event
  static constexpr uint16_t AUTORESET = 0x80; // reset counters after a trigger
};


struct v830rom{
  static constexpr uint16_t pad1 =        0x4000; // ~0x4025, 19 shorts
  static constexpr uint16_t OUIMSB =      0x4026;
  static constexpr uint16_t pad2 =        0x4028;
  static constexpr uint16_t OUI =         0x402a;
  static constexpr uint16_t pad3 =        0x402c;
  static constexpr uint16_t OUILSB =      0x402e;
  static constexpr uint16_t pad4 =        0x4030;
  static constexpr uint16_t Version =     0x4032;
  static constexpr uint16_t pad5 =        0x4034;
  static constexpr uint16_t BoardIdMSB =  0x4036;
  static constexpr uint16_t pad6 =        0x4038;
  static constexpr uint16_t BoardId =     0x403a;
  static constexpr uint16_t pad7 =        0x403c;
  static constexpr uint16_t BoardIdLSB =  0x403e;
  static constexpr uint16_t pad8 =        0x4040; // ~0x404d, 7 shorts
  static constexpr uint16_t Revision =    0x404e;
  static constexpr uint16_t pad9 =        0x4050; // ~0x40ff, 88 shorts
  static constexpr uint16_t pad10 =       0x4100; // ~0x4eff, 1792 shorts
  static constexpr uint16_t pad11 =       0x4f00;
  static constexpr uint16_t SerialMSB =   0x4f02;
  static constexpr uint16_t pad12 =       0x4f04;
  static constexpr uint16_t SerialLSB =   0x4f06;
};

#endif
